package com.lfy.ch01;

/**
 * 资源类，共享数据
 */
public class ShareDataOne {

    //  count = 0;
    private int count = 0; //资源  1 0 1 0




    // 等待的时候释放锁，方法执行完释放锁
    // 小口诀：判断（不该我干活，我就等）、干活（执行业务）、去通知（叫醒别人）
    // 等待：
    // 唤醒：
    public synchronized void increment() throws InterruptedException {

        //单次
//        if(a > 1){
//            ///
//        }
//
//        //循环
//        while (a > 1){
//
//        }
        //代码进来
        System.out.println(Thread.currentThread().getName() + "【加法】：抢到了锁");

        //1、判断不该我干活，我就等待
        while (count == 1) { //虚假唤醒
            System.out.println(Thread.currentThread().getName() + "【加法】：不该执行，等待并释放锁...");
            //说明已经加过了； 我们应该等待
            this.wait(); //等待，不执行任何代码。视觉效果和 sleep 差不多，啥也不干了，但是释放了锁
            // 一旦别人把 wait 的唤醒，代码就从wait的下一行继续执行
        }


        //2、如果上面if没进入，说明我可以执行
        System.out.println(Thread.currentThread().getName() + "【加法】：加1:" + ++count);

        //3、唤醒别人继续执行；【最想唤醒的是减操作】
        this.notifyAll(); //随机唤醒一个等待的线程。如果有多个线程在wait，则唤醒哪一个不确定
//        this.notifyAll(); //唤醒所有等待的线程。如果有多个线程在wait，则唤醒哪一个不确定
        System.out.println(Thread.currentThread().getName() + "【加法】：执行完成，且唤醒别人...");
    }

    public synchronized void decrement() throws InterruptedException {
        System.out.println(Thread.currentThread().getName() + "【减法】：抢到了锁");
        //1、判断不该我干活，我就等待
        while (count == 0) { //说明已经减过了;
            // if 导致虚假唤醒； 需要再次判断，如果还是不该我干活，那我继续等； 虚假唤醒的人有自觉性
            System.out.println(Thread.currentThread().getName() + "【减法】：不该执行，等待并释放锁...");
            this.wait(); //等待，不执行任何代码
            //再往下走
            //要执行下面的代码，1）、必须先抢到锁  2）、等到CPU分配时间片
        }


        //2、干活
        System.out.println(Thread.currentThread().getName() + "【减法】：减1:" + --count);


        //3、唤醒别人  // notifyAll 替代 notify 解决假死
        this.notifyAll(); //随机唤醒一个等待的线程。如果有多个线程在wait，则唤醒哪一个不确定
        System.out.println(Thread.currentThread().getName() + "【减法】：执行完成，且唤醒别人...");
    }

    public void aaa() throws InterruptedException {
        System.out.println("aaa");

        this.wait();
        System.out.println("bbb");
    }

}
